#ifndef BJHAND_H
#define BJHAND_H

#include "hand.h"
#include <string.h>

class BJConnection;

#define BJF_NORMAL		0x00000000L
#define BJF_DEAL		0x00000001L
#define BJF_BET			(BJF_DEAL)
#define BJF_HIT			0x00000002L
#define BJF_STAND		0x00000004L
#define BJF_DOUBLE		0x00000008L
#define BJF_SPLIT		0x00000010L
#define BJF_SURRENDER	0x00000020L
#define BJF_RAISE		0x00000040L
/// [2013-07-10] Charles. Added for supporting 'Zappit Rackcard'.
#define BJF_ZAP			0x00000080L

class BJHand : public Hand
{
	public:
		BJHand
		(
			CardMgr*	pMgr,
			bool8		isHardAces = false
		);
		~BJHand();

		bool8	IsNatural();
		bool8	IsAceShowing();

		int32	GetScoreHard();
		int32	GetScore();
		int32	GetNAces();

		int32	GetScoreHardVisible();
		int32	GetScoreVisible();
		int32	GetNAcesVisible();

		bool8	IsSoft();
		bool8	IsSoftAces();
		bool8	IsHardAces();
		bool8	IsAce( uint8 card );

		BJHand*	HandleSplit();
		/// [2013-07-10] Charles. Added for supporting 'Zappit Rackcard'.
		void HandleZap();

		bool8	add(uint8 Card, bool8 down=0 );

		int		wasAction( int action );
		void	setAction( int action );
		int32	GetActions();
		void	SetActions
		(
			uint8 bet,
			uint8 hit,
			uint8 stand,
			uint8 doubled,
			uint8 split,
			uint8 surrender,
			uint8 raise,
			uint8 zap						/// [2013-07-10] Charles. Added for supporting 'Zappit Rackcard'.
		);
		void SetAction( int action, uint8 val );

		void restore
		(
			uint8*	cards,
			int32	count,
			uint8	nBets,
			uint8	actions,
			int32	bonusBalanceBet,
			BJHand*	prev
		);

		void	SetCardFacingBits();
		void	ClrCardFacingBits();
		int		IsCardVisible( int nCard );
		void	RestoreCardFacingBits();
		void	RevealAllCards();

		void	send( BJConnection* );
		void	sendCards( BJConnection* conn );
		void	sendCard( int32 i, BJConnection* conn );
		void	sendLastCard( BJConnection* conn );

		int32	GetNCardsVisible();
		uint8	GetNBets();
		void	SetNBets( uint8 nBets );
		uint8	GetNHand();
		void	SetNHand( uint8 nHand );
		void	SetPayout( int32 payout );
		int32	GetPayout();
		void	SetBonus(int32 bonus);
		int32	GetBonus();
		void	SetBonusName( char* pBonusName );
		char*	GetBonusName();

		void	SetBonusBalanceBet( int32 bonus );
		int32	GetBonusBalanceBet();

		bool8	updateBalance() { return m_updateBalance; }
		void    balanceUpdated() { m_updateBalance = false; }


	protected:

		void	SetCardVisible( int nCard, int vis );

		int32	m_actionBits;
		uint32	m_cardFaceBits;	//0=face up, 1=face dn
		//face down cards are unknown to the player

		uint8	m_nBets;		//in terms of original game bet
		uint8	m_nHand;		//the hand number 0-n
		int32	m_payout;		//total money won/lost
		int32	m_bonus;		//money above and beyond the bet
		char	m_bonusName[32];//reason for bonus as in "BlackJack"
		bool8	m_isHardAces;
		bool8	m_updateBalance;

		int32 	m_bonusBalanceBet; //Amount of bet allocated from the bonus balance -- included because a split reorders the hand numbers
};

inline void
BJHand::SetBonus( int32 bonus )
{
	m_bonus = bonus;
}

inline int32
BJHand::GetBonus()
{
	return m_bonus;
}


inline void
BJHand::SetBonusBalanceBet( int32 bonus )
{
	m_bonusBalanceBet = bonus;
}

inline int32
BJHand::GetBonusBalanceBet()
{
	return m_bonusBalanceBet;
}


inline void
BJHand::SetBonusName( char* pBonusName )
{
	strncpy( m_bonusName, pBonusName, sizeof(m_bonusName) );
}

inline char*
BJHand::GetBonusName()
{
	return &m_bonusName[0];
}

inline void
BJHand::SetPayout( int32 payout )
{
	m_payout	= payout;

	m_nBets		= 0;
}

inline int32
BJHand::GetPayout()
{
	return m_payout;
}

inline int
BJHand::wasAction( int action )
{
	return ((m_actionBits & action) != 0);
}

inline void
BJHand::setAction( int action )
{
	m_actionBits |= action;
}

inline void
BJHand::SetAction( int action, uint8 val )
{
	if (val != 0)
		m_actionBits |= action;
	else
		m_actionBits &= (~action);
}


inline uint8
BJHand::GetNBets()
{
	return m_nBets;
}

inline void
BJHand::SetNBets( uint8 nBets )
{
	m_nBets = nBets;
}

inline int32
BJHand::GetActions()
{
	return (m_actionBits);
}

inline uint8
BJHand::GetNHand()
{
	return m_nHand;
}

inline void
BJHand::SetNHand( uint8 nHand )
{
	m_nHand = nHand;
}

inline void
BJHand::SetActions
(
	uint8 bet,
	uint8 hit,
	uint8 stand,
	uint8 doubled,
	uint8 split,
	uint8 surrender,
	uint8 raise,
	uint8 zap						/// [2013-07-10] Charles. Added for supporting 'Zappit Rackcard'.
)
{
	SetAction( BJF_BET		, bet		);
	SetAction( BJF_HIT		, hit		);
	SetAction( BJF_STAND	, stand		);
	SetAction( BJF_DOUBLE	, doubled	);
	SetAction( BJF_SPLIT	, split		);
	SetAction( BJF_SURRENDER, surrender );
	SetAction( BJF_RAISE	, raise		);
	/// [2013-07-10] Charles. Added for supporting 'Zappit Rackcard'.
	SetAction( BJF_ZAP, zap );
}

#endif
